package com.cqhilink.api.common.utils.annotation;

import com.cqhilink.api.common.utils.ConfigPropertyTool;
import com.cqhilink.api.common.utils.Constant;
import com.cqhilink.api.common.utils.grant.GrantUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 注解验证处理类
 *
 * @author 王镇
 * @create 2017-11-02 13:49
 */
public class AnnotationDealUtil {
    private static Logger logger = LoggerFactory.getLogger(AnnotationDealUtil.class);

    public static Map<String, Object> validate(Object bean) {
        Map<String, Object> result = new HashMap<>();
        result.put("message", "验证通过");
        result.put("result", true);
        Class<?> cls = bean.getClass();

        // 检测field是否存在
        try {

            // 获取实体字段集合
            Field[] fields = cls.getDeclaredFields();
            // 判断实体对象中的字段是否需要校验
            if (!fields(fields, bean).isEmpty())
                return fields(fields, bean);
            // 获取实体父类字段集合
            Field[] pfields = cls.getSuperclass().getDeclaredFields();
            // 判断实体对象父类中的字段是否需要校验
            if (!fields(pfields, bean).isEmpty())
                return fields(pfields, bean);

        } catch (Exception e) {
            e.printStackTrace();
            logger.info("验证出错");
        }
        return result;
    }

    /**
     * 遍历处理字段
     *
     * @param fields
     */
    private static Map<String, Object> fields(Field[] fields, Object bean) throws IllegalAccessException, InstantiationException {
        Map<String, Object> result = new HashMap<>();
        for (Field f : fields) {
            // 通过反射获取该属性对应的值
            f.setAccessible(true);
            // 获取字段值
            Object value = f.get(bean);
            // 获取字段上的注解集合
            Annotation[] arrayAno = f.getAnnotations();
            for (Annotation annotation : arrayAno) {
                // 获取注解类型（注解类的Class）
                Class<?> clazz = annotation.annotationType();
                // 获取注解类中的方法集合
                Method[] methodArray = clazz.getDeclaredMethods();
                for (Method method : methodArray) {
                    // 获取方法名
                    String methodName = method.getName();
                    // 过滤错误提示方法的调用
                    if (methodName.equals("message")) {
                        continue;
                    }
                    // 初始化注解验证的方法处理类 （我的处理方法卸载本类中）
                    Object obj = AnnotationDealUtil.class.newInstance();
                    // 获取方法
                    try {
                        Class aduclazz = Class.forName(AnnotationDealUtil.class.getName());

                        // 获取类中定义的方法
                        Method[] mths = aduclazz.getDeclaredMethods();
                        List<String> list = new ArrayList<>();
                        for (int i = 0; i < mths.length; i++) {
//                            logger.info("所有方法之:{}",mths[i].getName());
                            list.add(mths[i].getName());
//                            System.out.println("所有方法之" + mths[i].getName());
//                            System.out.println("修饰符类型：" + mths[i].getModifiers());
                        }
                        // 判断注解里面的方法名称是否在当前类型的方法名中
                        if (list.contains(methodName)){
                            // 根据方法名获取该方法
                            Method m = obj.getClass().getDeclaredMethod(methodName, Object.class, Field.class);
                            // 调用该方法
                            result = (Map<String, Object>) m.invoke(obj, value, f);
                            /* 验证结果 有一处失败则退出 */
                            if (result.get("result").equals(false)) {
                                return result;
                            }
                        }else {
                            return result;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        logger.info("找不到该方法:" + methodName);
                    }
                }
            }
        }
        return result;
    }

    /**
     * 验证是否包含此参数
     *
     * @param value 参数值
     * @param field 字段
     * @return
     * @author zhy
     */
    public Map<String, Object> isRight(Object value, Field field) {
        Map<String, Object> validateResult = new HashMap<>();
        RightAnnotation annotation = field.getAnnotation(RightAnnotation.class);

        // 获取配置文件中的作业区信息
        Map<String, Object> map = getLisence();
        if (map.isEmpty()) {
            // 判断白名单中是否存在指定的id
            if (Arrays.asList(Constant.WORK_ZONE).contains(value)) {
                validateResult.put("message", "验证通过");
                validateResult.put("result", true);
            } else {
                validateResult.put("message", value + annotation.message());
                validateResult.put("result", false);
            }
        } else {
            // 如果在文件中存在key则验证通过
            if (map.containsKey(value)) {
                validateResult.put("message", "验证通过");
                validateResult.put("result", true);
            } else {
                validateResult.put("message", value + annotation.message());
                validateResult.put("result", false);
            }
        }
        return validateResult;
    }

    /**
     * 获取文件地址
     * @return
     */
    private Map<String, Object> getLisence(){
        String path = ConfigPropertyTool.getValue("lisence");
        Map<String, Object> map = GrantUtil.grantMap(path);
        return map;
    }
}
